#ifndef __DRIVER_USB_H
#define __DRIVER_USB_H

#include <lib/list.h>
#include <os/driver.h>
#include <arch/pci.h>

#define DRIVER_NAME "usb-driver"
#define DRIVER_VER "0.1"

#define DEVICE_NAME "usb-controller"

// usb class
#define USB_CONTROLLER_CLASS 0xC
#define USB_CONTROLLER_SUBCLASS 0x3

// usb proIF
#define USB_UHCI_CONTROLLER_PROIF 0x0
#define USB_OHCI_CONTROLLER_PROIF 0x10
#define USB_EHCI_CONTROLLER_PROIF 0x20
#define USB_XHCI_CONTROLLER_PROIF 0x30
#define USB_USB_DEVICE_PROIF 0xFE

// usb hub type
#define USB_TYPE_UHCI 0x00
#define USB_TYPE_OHCI 0x01
#define USB_TYPE_EHCI 0x02
#define USB_TYPE_XHCI 0x03

typedef struct usb_root
{
    char name[DEVICE_NAME_LEN+1];
} usb_root_t;

typedef struct usb_bus
{
    uint8_t bus;
    char bus_name[DEVICE_NAME_LEN+1];
    struct usb_root root_hub;
} usb_bus_t;


typedef struct usb_devcie
{
    uint8_t port;
    uint32_t status;
    uint16_t type;
} usb_device_t;

typedef struct __device_extension
{
    irqno_t irq;
    address_t iobase;
    union
    {
        struct
        {
            uint32_t usb_command;
            uint32_t usb_status;
            uint32_t usb_interrupt_enable;
            uint32_t frame_number;
            uint32_t frame_list_base;
            uint32_t start_of_frame;
            uint32_t port1_status;
            uint32_t port2_status;
        } UHCI; // usb 1.0
        struct
        {
            uint32_t usb_command;

        } OCHI;
        struct
        {
            // capability register
            uint32_t cap_reg_len;
            uint32_t reserved;
            uint32_t interface_ver_num;
            uint32_t struct_param1;
            uint32_t struct_param2;
            uint32_t struct_param3;
            uint32_t cap_param1;
            uint32_t doorbell_off;
            uint32_t run_reg_space_off;
            uint32_t cap_param2;
            // operational register
            uint32_t usb_command;
#define USB_XHCI_CMD_REG_RUNSTOP (1 << 0)
#define USB_XHCI_CMD_REG_HUBRESET (1 << 1)
            uint32_t usb_status;
            uint32_t page_size;
            uint32_t device_notific_control;
            uint32_t command_ring_ctrl;
            uint32_t device_context_base_array;
            uint32_t configure;
            // port register
            uint32_t port_base;
#define USB_XHCI_PORT_REG_PORTSC 0x00
#define USB_XHCI_PORT_REG_PORTPMSC 0x04
#define USB_XHCI_PORT_REG_PORTLI 0x08
// xhci port status control register
#define USB_XHCI_PORT_STATUS_RESET (1 << 4)
#define USB_XHCI_PORT_STATUS_POWER (1 << 9)
#define USB_XHCI_PORT_STATUS_CURCON (1 << 0)
#define USB_XHCI_PORT_STATUS_ENABLE (1 << 1)
            // runtime register
            uint32_t micrframe_idx;
            uint32_t interrupt_reg_sets;
        } XHCI; // usb 3.0
    } hub_port;
    uint32_t max_ports;
    uint32_t iolen;
    uint8_t usb_type;      // controller type
    pci_dev_t *pci_device; // pci device object
    usb_bus_t *bus;        // usb bus object
} device_extension_t;

#endif